﻿Imports <xmlns:eopr="http://schemas.microsoft.com/xps/2005/06">
Imports Google.Desktop
Imports Google.Desktop.Interop
Imports System.Runtime.InteropServices
Imports System.Reflection
Imports System.IO.Packaging
Imports System.Windows.Xps.Packaging
Imports System.Windows.Xps
Imports System.Text
Imports System.IO
Imports System.Xml.Linq
Imports System.Configuration




<ComClass(Indexer.ClassId, Indexer.InterfaceId, Indexer.EventsId)> _
Public Class Indexer
    Implements DGoogleDesktopFileNotify





#Region "COM GUIDs"
    ' These  GUIDs provide the COM identity for this class 
    ' and its COM interfaces. If you change them, existing 
    ' clients will no longer be able to access the class.
    Public Const ClassId As String = "239bc1c7-be1e-46b0-988c-26ee22fac946"
    Public Const InterfaceId As String = "fdf5221a-62cd-4a9b-8a76-349443368b3b"
    Public Const EventsId As String = "00ea6e61-9d28-43a4-b127-d305f8608988"
#End Region

   

    ' A creatable COM class must have a Public Sub New() 
    ' with no parameters, otherwise, the class will not be 
    ' registered in the COM registry and cannot be created 
    ' via CreateObject.
    Public Sub New()
        MyBase.New()

        ' SettingLog()
        ' 设置日志
        Dim t As Type = GetType(Indexer)

        Dim LogLocation = My.Computer.FileSystem.CombinePath(My.Computer.FileSystem.GetParentPath(t.Assembly.Location), "log")

        With My.Application.Log.DefaultFileLogWriter

            .CustomLocation = LogLocation
            .Location = Logging.LogFileLocation.Custom
            .BaseFileName = "log"
            .LogFileCreationSchedule = Logging.LogFileCreationScheduleOption.None
            .AutoFlush = True

        End With

        My.Application.Log.WriteEntry("Assembly.Location :" & t.Assembly.Location, TraceEventType.Information)

        Dim config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)

        My.Application.Log.WriteEntry("Config File : " & config.FilePath & " Has File :" & config.HasFile)

    End Sub



    ''' <summary>
    ''' 记录异常
    ''' </summary>
    ''' <param name="ex">异常</param>
    ''' <param name="additionalInfo">额外信息</param>
    ''' <returns>始终Fasle</returns>
    ''' <remarks></remarks>
    Private Shared Function LogException(ByVal ex As Exception, ByVal additionalInfo As String) As Boolean
        My.Application.Log.WriteException(ex, TraceEventType.Error Or TraceEventType.Critical Or TraceEventType.Warning, additionalInfo)
        Return False
    End Function


    ''' <summary>
    ''' 注册插件
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared Sub RegisterIndexer()
        Try

            Dim myAssembly As [Assembly] = GetType(Indexer).Assembly
            Dim asminfo As New ApplicationServices.AssemblyInfo(myAssembly)
            Dim iconpath = My.Computer.FileSystem.CombinePath(myAssembly.Location, "xpsfile.ico")

            IndexingComponentRegister.Register(GetType(Indexer), asminfo.Title, asminfo.Description, iconpath & ",0", "xps")

        Catch ex As Exception When LogException(ex, "RegisterIndexer")

        Catch ex As ComponentAlreadyRegisteredException
            MsgBox(My.Resources.Messages.ComponentAlreadyRegistered, MsgBoxStyle.Information Or MsgBoxStyle.OkOnly)

        Catch ex As ExtensionRegisteredException
            MsgBox(My.Resources.Messages.ExtensionRegistered, MsgBoxStyle.Exclamation Or MsgBoxStyle.OkOnly)
            UnregisterIndexer()
        Catch ex As RegistrationCancelledByUserException
            MsgBox(My.Resources.Messages.RegistrationCancelledByUser, MsgBoxStyle.Information Or MsgBoxStyle.OkOnly, "Registration")

        Catch ex As GoogleDesktopException
            MsgBox(ex.Message, MsgBoxStyle.Information Or MsgBoxStyle.OkOnly)
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Exclamation Or MsgBoxStyle.OkOnly)
        End Try
    End Sub

    ''' <summary>
    ''' 卸载插件
    ''' </summary>
    ''' <remarks></remarks>
    Public Shared Sub UnregisterIndexer()
        Try
            IndexingComponentRegister.Unregister(GetType(Indexer))
        Catch ex As Exception When LogException(ex, "UnregisterIndexer")

        Catch ex As ComponentNotRegisteredException
            MsgBox(My.Resources.Messages.ComponentNotRegistered, MsgBoxStyle.Critical Or MsgBoxStyle.OkOnly)
        Catch ex As GoogleDesktopException
            MsgBox(ex.Message, MsgBoxStyle.Information Or MsgBoxStyle.OkOnly)
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Exclamation Or MsgBoxStyle.OkOnly)
        End Try
    End Sub



    ''' <summary>
    ''' Google爬虫，文件处理
    ''' </summary>
    ''' <param name="filename">文件名</param>
    ''' <param name="event_factory">事件工厂</param>
    ''' <remarks></remarks>
    Public Sub HandleFile(ByVal filename As String, ByVal event_factory As Object) Implements DGoogleDesktopFileNotify.HandleFile
        If String.IsNullOrEmpty(filename) Then
            My.Application.Log.WriteEntry(String.Format("HandleFile :  Try to Send NOT EXIST File: {0}  ", filename), TraceEventType.Information Or TraceEventType.Warning)
            Return
        ElseIf event_factory Is Nothing Then
            My.Application.Log.WriteEntry("HandleFile : event_factory is Nothing ! ", TraceEventType.Information Or TraceEventType.Warning Or TraceEventType.Error)
            Return
        End If

        Try
            My.Application.Log.WriteEntry(String.Format("HandleFile Start :START: {0}", filename), TraceEventType.Information Or TraceEventType.Start)

            Dim Textfile As TextFile = GetTextFile(filename)

            Dim eve = Textfile.CreateEvent(GetType(Indexer), event_factory)

            eve.Send(EventFlags.EventFlagIndexable Or EventFlags.EventFlagHistorical)

            My.Application.Log.WriteEntry(String.Format("HandleFile :END: {0}", filename), TraceEventType.Information Or TraceEventType.Stop)

        Catch ex As Exception When LogException(ex, String.Format("HandleFile :ERROR: {0} ", filename))

        End Try
    End Sub

    ''' <summary>
    ''' 手工发送事件
    ''' </summary>
    ''' <param name="filename">文件名</param>
    ''' <remarks></remarks>
    Public Sub SendEvent(ByVal filename As String)

        If String.IsNullOrEmpty(filename) Then
            My.Application.Log.WriteEntry(String.Format("SendEvent : Try to Send NOT EXIST File: {0}", filename), TraceEventType.Information Or TraceEventType.Warning)
            Return
        End If
        Try
            My.Application.Log.WriteEntry("SendEvent :START: " & filename, TraceEventType.Information Or TraceEventType.Start)

            Dim Textfile As TextFile = GetTextFile(filename)

            Dim eve = Textfile.CreateEvent(GetType(Indexer))

            eve.Send(EventFlags.EventFlagIndexable)

            My.Application.Log.WriteEntry("SendEvent :END: " & filename, TraceEventType.Information Or TraceEventType.Stop)

        Catch ex As Exception When LogException(ex, String.Format("SendEvent :ERROR: {0}", filename))
        Catch ex As ComponentDisabledException
            MsgBox(My.Resources.Messages.ComponentDisabled, MsgBoxStyle.Information Or MsgBoxStyle.OkOnly)

        Catch ex As ComponentNotRegisteredException
            MsgBox(My.Resources.Messages.ComponentNotRegistered, MsgBoxStyle.Critical Or MsgBoxStyle.OkOnly)

        Catch ex As ServiceIsExitingException
            MsgBox(My.Resources.Messages.ServiceIsExiting, MsgBoxStyle.Information Or MsgBoxStyle.OkOnly)

        Catch ex As ServiceNotRunningException
            MsgBox(My.Resources.Messages.ServiceNotRunning, MsgBoxStyle.Information Or MsgBoxStyle.OkOnly)

        Catch ex As GoogleDesktopException
            MsgBox(ex.Message, MsgBoxStyle.Information Or MsgBoxStyle.OkOnly)
        Catch ex As Exception
            Throw
        End Try
    End Sub

    ''' <summary>
    ''' 生成 TextFile 对象
    ''' </summary>
    ''' <param name="filename"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function GetTextFile(ByVal filename As String) As TextFile

        Dim info = GetXpsInfo(filename)
        Return New TextFile(info.Content, IndexFormats.HTML, filename, info.LastModifiedTime) With {.Title = info.Title, .Author = info.Author}
    End Function

    Private Shared Function GetXpsInfo(ByVal filename As String) As XpsInfo

        Dim FileInfo As FileInfo = My.Computer.FileSystem.GetFileInfo(filename)

        Dim cachelen As Integer = CInt(FileInfo.Length * 2)

        Using xpsfile As New XpsDocument(filename, FileAccess.Read)

            My.Application.Log.WriteEntry(String.Format("GetXpsInfo :  Created and Reading XPSDocument : {0}", filename), TraceEventType.Information Or TraceEventType.Start)

            Dim contentsb As StringBuilder = New StringBuilder(cachelen)

            If xpsfile.FixedDocumentSequenceReader IsNot Nothing Then

                Dim FixedDocuments = xpsfile.FixedDocumentSequenceReader.FixedDocuments

                For Each doc In FixedDocuments

                    Dim pages = doc.FixedPages

                    For Each page In pages

                        Dim pagedoc = Xml.Linq.XDocument.Load(page.XmlReader)
                        Dim strs = From Glyphs In pagedoc...<eopr:Glyphs> _
                                   Select Glyphs.@UnicodeString

                        For Each s In strs
                            contentsb.AppendLine(s)
                        Next
                        contentsb.AppendLine()
                    Next
                    contentsb.AppendLine()
                Next
            End If




            Dim title As String = If(Not String.IsNullOrEmpty(xpsfile.CoreDocumentProperties.Title), xpsfile.CoreDocumentProperties.Title, FileInfo.Name)
            Dim creator As String = If(Not String.IsNullOrEmpty(xpsfile.CoreDocumentProperties.Creator), xpsfile.CoreDocumentProperties.Creator, String.Empty)
            Dim fileLastModifiedTime As Date = If(xpsfile.CoreDocumentProperties.Created IsNot Nothing, xpsfile.CoreDocumentProperties.Created, FileInfo.LastWriteTime)

            My.Application.Log.WriteEntry(String.Format("GetXpsInfo : filename: {0}  content size: {1}  title: {2} Author: {3} LastModifiedTime: {4} ", _
                                                                            filename, contentsb.Length, title, creator, fileLastModifiedTime), TraceEventType.Information Or TraceEventType.Stop)

            Return New XpsInfo(filename, contentsb.ToString, title, creator, fileLastModifiedTime)
        End Using
    End Function



    ''' <summary>
    ''' 读取Xps文件
    ''' </summary>
    Public Function ReadXps(ByVal filename As String) As String

        Dim info = GetXpsInfo(filename)

        Return info.Content
    End Function



End Class


